<!-- 组件 - 渲染内容元素 -->
<script>
import { typeOf, isVNode } from '../utils';

export default {
  name: 'BaseRender',
  props: {
    data: {
      type: [String, Boolean, Object, Array],
      default: '',
    },
  },
  /**
   * createElement(tag,dataObj,children) 接收三个参数
   * @param tag 要渲染的标签名，或者一个组件选项对象
   * @param dataObj  可以是一个字符串或一个对象。为对象时，可包含如下属性: props, attrs, class, style, on, nativeOn, directives, scopedSlots, slot, key, ref, refInFor 等
   * 完整属性详见：https://v2.cn.vuejs.org/v2/guide/render-function.html#%E6%B7%B1%E5%85%A5%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1
   * @param children 子 VNode，可以是 VNode 或者字符串 / 数组
   */
  render(createElement) {
    const { data } = this;
    const t = typeOf(data);
    // 如果是引入的组件或者是虚拟dom
    if (t === 'Object') {
      if (data.render || isVNode(data))
        return createElement('component', { is: data });
      throw new Error(`请传入一个引入的Vue组件或虚拟DOM`);
    }
    // 如果是数组，则传入的是创建虚拟dom需要的参数
    // 传参规则详见：https://v2.cn.vuejs.org/v2/guide/render-function.html#%E5%AE%8C%E6%95%B4%E7%A4%BA%E4%BE%8B
    if (t === 'Array') {
      const [comp, dataObj, children] = data;
      let newAttrs = dataObj;
      // 如果是复杂数据类型，则需要解构一下，移除响应性监听
      if (typeOf(dataObj) === 'Object') newAttrs = { ...dataObj };
      return createElement(comp, newAttrs, children);
    }
    // 如果是基本数据类型
    return createElement('div', data);
  },
};
</script>
